package com.adcc.swingui.factory;

import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JRadioButtonMenuItem;

import org.apache.log4j.Logger;

import com.adcc.swingui.base.DefaultMenuBar;
import com.adcc.swingui.bean.MenuBean;
import com.adcc.swingui.bean.MenuComponentBean;
import com.adcc.swingui.conf.MenuBarConf;
import com.jidesoft.action.CommandBar;
import com.jidesoft.action.CommandMenuBar;
import com.jidesoft.action.DefaultDockableBarDockableHolder;

/**
 * 菜单创建工厂
 * 
 * @author charlie
 * 
 */
public class MenuBarFactory {
	private static Logger logger = Logger.getLogger(MenuBarFactory.class);
	private static Map<String, CommandBar> map = new HashMap<String, CommandBar>();
	private static final String EVENT_METHOD = "method";
	private static final String EVENT_WEB = "web";
	private static final String EVENT_EXE = "exe";
	private static  List<JComponent> itemList ;
	
	@Deprecated
	public static void create(String[] name, Container container) {
		for (int i = 0; i < name.length; i++) {
			if (map.containsKey(name[i])) {
				logger.warn("菜单对象已经存在" + name[i]);
			}
			MenuBean bean = MenuBarConf.getMenuConf().get(name[i]);
			CommandBar commandBar = new CommandMenuBar(name[i]);
			if (bean != null) {
				commandBar.setInitIndex(0);
				commandBar.setPaintBackground(false);
				commandBar.setStretch(true);
				commandBar.setFloatable(true);
				commandBar.setHidable(false);
				for (MenuComponentBean component : bean.getMenuList()) {
					try {
						// if (component == null)
						// continue;
						Class c = Class.forName(component.getEventAction());
						Constructor con = c.getConstructor(new Class[] { Container.class });
						DefaultMenuBar o = (DefaultMenuBar) con.newInstance(container);
						JComponent jcomp = o.buildButton(o.getClass().getName());
						jcomp.setVisible(component.getOffLineVisiable());
						jcomp.setEnabled(component.getCompEnabled());
						commandBar.add(jcomp);
						// ADD MENU&MENUITEM
						// 二级菜单
						List<JComponent> jcomps = new ArrayList<JComponent>();
						jcomps.add(jcomp);
						if (component != null && component.getItemList() != null) {
							ButtonGroup menuGroup = new ButtonGroup();
							for (MenuComponentBean ib2 : component.getItemList()) {
								Class c2 = Class.forName(component.getEventAction());
								// 判断是不包含子项则增加JMenuItem，如果包含子项则增加JMenu
								if (ib2.getItemList() != null && ib2.getItemList().size() > 0) {
									ButtonGroup itemGroup = new ButtonGroup();
									JMenu m2 = (JMenu) c2.newInstance();
									m2.setText(ib2.getName());
									if (ib2.getIcon() != null && !"".equals(ib2.getIcon())) {
										m2.setIcon(new ImageIcon(ib2.getIcon()));
									}
									m2.setVisible(ib2.getOffLineVisiable());
									m2.setEnabled(ib2.getCompEnabled());
									o.getSourceComp().add(m2);
									// 三级菜单
									for (MenuComponentBean ib3 : ib2.getItemList()) {
										JMenuItem menuItem = createMenuItem(c, ib3);
										if (JRadioButtonMenuItem.class.getName().equals(ib3.getEventAction())) {
											itemGroup.add(menuItem);
										}
										menuItem.setVisible(ib3.getOffLineVisiable());
										menuItem.setEnabled(ib3.getCompEnabled());
										m2.add(menuItem);
										jcomps.add(menuItem);
									}
									// 设置JRadioButtonMenuItem默认选择项
									if (itemGroup.getButtonCount() > 0) {
										JRadioButtonMenuItem rdbItem = (JRadioButtonMenuItem) itemGroup.getElements()
												.nextElement();
										rdbItem.setSelected(true);
									}
									jcomps.add(m2);
								} else {
									JMenuItem menuItem = createMenuItem(c, ib2);
									if (JRadioButtonMenuItem.class.getName().equals(ib2.getEventAction())) {
										menuGroup.add(menuItem);
									}
									o.getSourceComp().add(menuItem);
									menuItem.setVisible(ib2.getOffLineVisiable());
									menuItem.setEnabled(ib2.getCompEnabled());
									jcomps.add(menuItem);
								}
							}
							// 设置JRadioButtonMenuItem默认选择项
							if (menuGroup.getButtonCount() > 0) {
								JRadioButtonMenuItem rdbItem = (JRadioButtonMenuItem) menuGroup.getElements()
										.nextElement();
								rdbItem.setSelected(true);
							}
						}
						try {
							Method mtd = c.getDeclaredMethod("i18nItems", List.class);
							mtd.invoke(o, jcomps);
						} catch (NoSuchMethodException nsme) {
							continue;
						}
					} catch (Exception e) {
						e.printStackTrace();
						logger.error("工具创建失败" + component.getEventAction() + e.getMessage());
					}
				}
			} else {
				logger.error("菜单对象配置不存在" + name[i]);
			}

			// 菜单缓存到内存
			map.put(name[i], commandBar);
			// 添加到容器显示
			((DefaultDockableBarDockableHolder) container).getDockableBarManager().addDockableBar(commandBar);
		}
	}
	
	
	/**   
	 * @Title: createNew   
	 * @Description: TODO  构建菜单
	 * @param @param name
	 * @param @param container  
	 * @return void  
	 * @throws   
	 */
	public static void createNew(String[] name, Container container) {

		for (int i = 0; i < name.length; i++) {

			if (map.containsKey(name[i])) {
				logger.warn("菜单对象已经存在" + name[i]);
			}

			MenuBean bean = MenuBarConf.getMenuConf().get(name[i]);

			CommandBar commandBar = new CommandMenuBar(name[i]);

			if (bean != null) {

				commandBar.setInitIndex(0);
				commandBar.setPaintBackground(false);
				commandBar.setStretch(true);
				commandBar.setFloatable(true);
				commandBar.setHidable(false);

				for (MenuComponentBean rootMenuBean : bean.getMenuList()) {// 遍历所有菜单项

					try {

						JMenu rootMenu;// 根菜单

						// 如果menuClass不为JMenu类型，则反射实例化
						if (rootMenuBean.getMenuClass().equals(JMenu.class.getName())) {
							rootMenu = new JMenu();
						} else if (rootMenuBean.getMenuClass().equals("impl")) {
							Class c = Class.forName(rootMenuBean.getEventAction());
							Constructor con = c.getConstructor(new Class[] { Container.class });
							DefaultMenuBar o = (DefaultMenuBar) con.newInstance(container);
							rootMenu = (JMenu) o.buildButton(o.getClass().getName());
						} else {
							Class menuClazz = Class.forName(rootMenuBean.getMenuClass());
							Constructor con = menuClazz.getConstructor();
							rootMenu = (JMenu) con.newInstance();
						}
						// 设置菜单属性
						rootMenu.setText(rootMenuBean.getI18nName());
						rootMenu.setVisible(rootMenuBean.getOffLineVisiable());
						rootMenu.setEnabled(rootMenuBean.getCompEnabled());
						rootMenu.setOpaque(false);
						commandBar.add(rootMenu);

						itemList = new ArrayList<JComponent>();// 收集所有菜单项
						itemList.add(rootMenu);

						// 构建子菜单
						if (rootMenuBean.getItemList() != null && rootMenuBean.getItemList().size() > 0) {
							processMenuItem(rootMenu, rootMenuBean, container);
						}

						String eventType = rootMenuBean.getEventType();// 得到eventType

						if (eventType.equals(EVENT_METHOD) && rootMenuBean.getEventAction().contains(".") && !rootMenuBean.getEventAction().contains("/")) {// 如果为Method，缓存到内存中
							try {
								Class defClzz = Class.forName(rootMenuBean.getEventAction());
								Constructor defCon = defClzz.getConstructor(new Class[] { Container.class });
								DefaultMenuBar defaultMenuBar = (DefaultMenuBar) defCon.newInstance(container);
								defaultMenuBar.getMenuBarMap().put(rootMenuBean.getEventAction(), defaultMenuBar);
								// 国际化
								boolean isMethod = false;
								for (Method m : defClzz.getDeclaredMethods()) {
									if (m.getName().equals("i18n")) {
										isMethod = true;
										break;
									}
								}
								Method mtd;
								if (isMethod) {
									mtd = defClzz.getDeclaredMethod("i18n", new Class[] { String.class, List.class });
								} else {
									mtd = defClzz.getSuperclass().getDeclaredMethod("i18n", new Class[] { String.class, List.class });
								}
								mtd.invoke(defaultMenuBar, defClzz.getName(), itemList);
								
								//离线
								Method offLineMtd = defClzz.getDeclaredMethod("offLineVisiable", List.class);
								offLineMtd.setAccessible(true);
								offLineMtd.invoke(defaultMenuBar,  itemList);
							} catch (NoSuchMethodException nsme) {
								continue;
							}
						}

						DefaultMenuBar.setMenuMap(rootMenuBean.getName(), rootMenu);// 缓存非叶子菜单

					} catch (Exception e) {
						e.printStackTrace();
						logger.error("工具创建失败" + rootMenuBean.getEventAction() + e.getMessage());
					}
				}
			} else {
				logger.error("菜单对象配置不存在" + name[i]);
			}

			// 菜单缓存到内存
			map.put(name[i], commandBar);
			// 添加到容器显示
			((DefaultDockableBarDockableHolder) container).getDockableBarManager().addDockableBar(commandBar);
		}
	}
	
	
	/**   
	 * @Title: processMenuItem   
	 * @Description: TODO  递归构建菜单结构
	 * @param @param rootMenu 根节点
	 * @param @param rootMenuBean 根节点封装类
	 * @param @param container  
	 * @return void  
	 * @throws   
	 */
	private static void processMenuItem(JComponent rootMenu, MenuComponentBean rootMenuBean, final Container container) {
		
		ButtonGroup group = new ButtonGroup();
		
		for (final MenuComponentBean menuBean : rootMenuBean.getItemList()) {

			try {

				JComponent jcomp;

				// 判断是否为默认菜单组件，如果不是就反射构造
				if (menuBean.getMenuClass().equals(JMenu.class.getName())) {
					jcomp = new JMenu();
				} else if (menuBean.getMenuClass().equals(JMenuItem.class.getName())) {
					jcomp = new JMenuItem();
				} else if (menuBean.getMenuClass().equals(JRadioButtonMenuItem.class.getName())) {
					jcomp = new JRadioButtonMenuItem();
				} else if (menuBean.getMenuClass().equals(JCheckBoxMenuItem.class.getName())) {
					jcomp = new JCheckBoxMenuItem();
				} else if(rootMenuBean.getMenuClass().equals("impl")){//自定义实现
					Class c = Class.forName(rootMenuBean.getEventAction());
					Constructor con = c.getConstructor(new Class[] { Container.class });
					DefaultMenuBar o = (DefaultMenuBar) con.newInstance(container);
					jcomp =o.buildButton(o.getClass().getName());
				}else {
					Class menuClazz = Class.forName(menuBean.getMenuClass());
					Constructor con = menuClazz.getConstructor();
					jcomp = (JComponent) con.newInstance();
				}
				itemList.add(jcomp);
				// 设置菜单属性
				jcomp.setVisible(menuBean.getOffLineVisiable());
				jcomp.setEnabled(menuBean.getCompEnabled());
				rootMenu.add(jcomp);

				if (menuBean.getLeaf()) {// 如果为子节点，则注册监听事件
					JMenuItem menuItem = (JMenuItem) jcomp;
					menuItem.setText(menuBean.getI18nName());
					if (menuBean.getIcon() != null && !"".equals(menuBean.getIcon())) {
						menuItem.setIcon(new ImageIcon(menuBean.getIcon()));
					}
					menuItem.addActionListener(new ActionListener() {
						@Override
						public void actionPerformed(ActionEvent e) {
							// TODO Auto-generated method stub
							menuItemAcion(menuBean, container);// 事件监听
						}
					});
				
					if (JRadioButtonMenuItem.class.getName().equals(menuBean.getMenuClass())) {
						group.add(menuItem);
					}

					DefaultMenuBar.setMenuChildMap(menuBean.getName(), menuItem);// 缓存子菜单

				} else {// 如果是根节点则递归检索其子节点

					JMenu menu = (JMenu) jcomp;

					menu.setText(menuBean.getI18nName());

					if (menuBean.getIcon() != null && !"".equals(menuBean.getIcon())) {
						menu.setIcon(new ImageIcon(menuBean.getIcon()));
					}
					
					DefaultMenuBar.setMenuMap(menuBean.getName(), menu);//缓存非叶子菜单
					
					processMenuItem(jcomp, menuBean, container);// 递归
				}

			} catch (Exception e) {
				logger.error("工具创建失败" + menuBean.getEventAction(), e);
			}
		}
		
		// 设置JRadioButtonMenuItem默认选择项
		if (group.getButtonCount() > 0) {
			JRadioButtonMenuItem rdbItem = (JRadioButtonMenuItem) group.getElements().nextElement();
			rdbItem.setSelected(true);
		}

	}

	/**   
	 * @Title: menuItemAcion   
	 * @Description: TODO 菜单响应事件 
	 * @param @param menuBean
	 * @param @param container  
	 * @return void  
	 * @throws   
	 */
	private static void menuItemAcion(MenuComponentBean menuBean, Container container) {
		String eventType = menuBean.getEventType();
		try {
			if (eventType.equals(EVENT_METHOD)) {

				String[] classNameOrMethod = menuBean.getEventAction().split(":");
				String className = classNameOrMethod[0];
				String methodName = classNameOrMethod[1];
				Class c = Class.forName(className);
				Constructor con = c.getConstructor(new Class[] { Container.class });
				DefaultMenuBar o = (DefaultMenuBar) con.newInstance(container);
				Method mtd = c.getDeclaredMethod(methodName, null);
				mtd.invoke(c.newInstance(), null);

			} else if (eventType.equals(EVENT_EXE)) {
				String exePath = null;
				if (menuBean.getEventAction().startsWith("/")) {
					exePath= System.getProperty("user.dir")+menuBean.getEventAction();
				} else {
					exePath = menuBean.getEventAction();
				}
				Runtime.getRuntime().exec(exePath);

			} else if (eventType.equals(EVENT_WEB)) {

				String url = menuBean.getEventAction();
				// 获取操作系统的名字
				String osName = System.getProperty("os.name", "");
				if (osName.startsWith("Mac OS")) {
					// 苹果的打开方式
					Class fileMgr = Class.forName("com.apple.eio.FileManager");
					Method openURL = fileMgr.getDeclaredMethod("openURL", new Class[] { String.class });
					openURL.invoke(null, new Object[] { url });
				} else if (osName.startsWith("Windows")) {
					// windows的打开方式。
					Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + url);
				} else {
					// Unix or Linux的打开方式
					String[] browsers = { "firefox", "opera", "konqueror", "epiphany", "mozilla", "netscape" };
					String browser = null;
					for (int count = 0; count < browsers.length && browser == null; count++)
						// 执行代码，在brower有值后跳出，
						// 这里是如果进程创建成功了，==0是表示正常结束。
						if (Runtime.getRuntime().exec(new String[] { "which", browsers[count] }).waitFor() == 0)
							browser = browsers[count];
					if (browser == null)
						throw new Exception("Could not find web browser");
					else
						// 这个值在上面已经成功的得到了一个进程。
						Runtime.getRuntime().exec(new String[] { browser, url });
				}
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			JOptionPane.showMessageDialog(container, "无法打开" + menuBean.getEventAction());
		} catch (Exception ex) {
			// TODO: handle exception
			ex.printStackTrace();
		}
	}
	
	
 

	/**
	 * 增加 JMenuItem子项
	 * 
	 * @param clazz
	 * @param bean
	 * @return
	 * @throws Exception
	 */
	@Deprecated
	private static JMenuItem createMenuItem(final Class parentClazz, final MenuComponentBean bean) throws Exception {
		JMenuItem mi = null;
		String clazzName = bean.getEventAction();
		// Class cls = Class.forName(clazzName);
		if (JMenuItem.class.getName().equals(clazzName)) {
			mi = new JMenuItem();
		} else if (JRadioButtonMenuItem.class.getName().equals(clazzName)) {
			mi = new JRadioButtonMenuItem();
		} else if (JCheckBoxMenuItem.class.getName().equals(clazzName)) {
			mi = new JCheckBoxMenuItem();
		}
		mi.setText(bean.getI18nName());
		if (bean.getIcon() != null && !"".equals(bean.getIcon())) {
			mi.setIcon(new ImageIcon(bean.getIcon()));
		}
		mi.setEnabled(bean.getCompEnabled());
		mi.setEnabled(bean.getOffLineVisiable());
		if (bean.getMethod() != null && !"".equals(bean.getMethod())) {
			mi.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					try {
						Method mtd = parentClazz.getDeclaredMethod(bean.getMethod(), null);
						mtd.invoke(parentClazz.newInstance(), null);
					} catch (Exception ex) {
						logger.error("Must contain no argument constructor");
						ex.printStackTrace();
					}
				}
			});
		}
		return mi;
	}
}
